package biz.datalk.industrialland.common.component.filter;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.PathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;

/**
 * 使 requestBody 中的流可以读取多次
 *
 * @author tarofang@163.com
 * @date 2019-09-15
 */
public class RequestBodyReaderFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(RequestBodyReaderFilter.class);

    public static final String INIT_PARAM_EXCLUDE_PATTERNS = "excludePatterns";

    private PathMatchingResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver();

    private String[] excludePatterns;


    @Override
    public void init(FilterConfig filterConfig) {
        String excludePatternsStr = filterConfig.getInitParameter(INIT_PARAM_EXCLUDE_PATTERNS);
        String staticExcludePathPatterns = StringUtils.trimToEmpty(excludePatternsStr);
        String[] excludePatterns = StringUtils.splitByWholeSeparatorPreserveAllTokens(staticExcludePathPatterns, ",");
        if (ArrayUtils.getLength(excludePatterns) > 0) {
            excludePatterns = Arrays.stream(excludePatterns).map(String::trim).toArray(String[]::new);
        }
        this.excludePatterns = excludePatterns == null ? new String[0] : excludePatterns;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //add 2020-04-05 by fangtl S
        if (!(servletRequest instanceof HttpServletRequest)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String reqUri = request.getRequestURI();

        // 跳过指定URI
        if (isSkipUri(reqUri)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }

        String contentType = StringUtils.trimToEmpty(request.getHeader("Content-Type"));
        String jsonContentType = "application/json";
        // String multipartContentType = "multipart/form-data";
        // 请求包装，允许多次读取参数
        if (StringUtils.startsWithIgnoreCase(contentType, jsonContentType)) {
            filterChain.doFilter(new RequestBodyReaderHttpServletRequestWrapper(request), servletResponse);

        }
        // 在该处配置，不能使用配置修改相关参数
        // @see biz.datalk.cloudfile.config.MultipartResolverConfig
        // 配置文件上传解析器，解决 spring 切面中无法获取其他参数
        // else if (StringUtils.containsIgnoreCase(contentType, multipartContentType)) {
        //     // 默认使用 StandardServletMultipartResolver
        //     CommonsMultipartResolver resolver = new CommonsMultipartResolver(servletRequest.getServletContext());
        //     MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart((HttpServletRequest) servletRequest);
        //     filterChain.doFilter(multipartRequest, servletResponse);
        // }
        else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
        //add 2020-04-05 by fangtl E

        //delete 2020-04-05 by fangtl S
        //ServletRequest requestWrapper = null;
        //if (servletRequest instanceof HttpServletRequest) {
        //    String reqUri = ((HttpServletRequest) servletRequest).getRequestURI();
        //    if (StringUtils.contains(reqUri, "/sys/common/upload")) {
        //        // not do nothing // 文件上传 不做处理
        //    } else {
        //        requestWrapper = new RequestBodyReaderHttpServletRequestWrapper((HttpServletRequest) servletRequest);
        //    }
        //}
        //
        //
        //if (requestWrapper == null) {
        //    filterChain.doFilter(servletRequest, servletResponse);
        //} else {
        //    filterChain.doFilter(requestWrapper, servletResponse);
        //}
        //delete 2020-04-05 by fangtl E
    }

    @Override
    public void destroy() {
    }

    private boolean isSkipUri(String uri) {
        if (ArrayUtils.getLength(excludePatterns) <= 0) {
            return false;
        }

        PathMatcher pathMatcher = resourceLoader.getPathMatcher();

        boolean result = false;
        for (String excludePattern : excludePatterns) {
            result = pathMatcher.match(excludePattern, uri);
            if (result) {
                break;
            }
        }

        return result;
    }
}
